package cn.ml.sheJiMoShi.single.lanHan;

import java.lang.reflect.Constructor;

public class Lazy2_jaiSuo {
    private volatile static Lazy2_jaiSuo lazy2;
    private Lazy2_jaiSuo(){
        synchronized (Lazy2_jaiSuo.class){
            if(lazy2!= null){
                throw new RuntimeException("不要试图使用反射破坏异常");
            }
        }
        System.out.println(Thread.currentThread().getName() + "ok");
    }

    public static Lazy2_jaiSuo getInstance(){
        //双重检测锁模式的懒汉式单例 DCL懒汉式
        if (lazy2 == null) {
            synchronized (Lazy2_jaiSuo.class) { // 类加锁此类对象只有一个
                if (lazy2 == null) {
                    lazy2 = new Lazy2_jaiSuo(); //不是一个原子性操作，底层有三步，如下：
                    /**
                     * 1、分配内存空间
                     * 2、执行构造方法，初始化对象
                     * 3、将这个对象指向空间
                     *
                     * 正确步骤是 1 2 3
                     * 可能步骤是 1 3 2
                     * 当A线程走 1 3 2 步骤走到3时已经指向空间了 B线程进来了就会判断lazy2不等于null，
                     * 就会return lazy2,此时lazy2还没有完成构造 空间为虚无的，所以为了安全要在方法上要加 volatile
                     */
                }
            }
        }
        return lazy2;
    }

    //测试多线程是否安全
    /*public static void main(String[] args) {
        for (int i = 0; i < 10 ; i++){
            new Thread(()->{
                Lazy2_jaiSuo.getInstance();
            }).start();
        }
    }*/
    // 反射！可以破坏单例
    public static void main(String[] args) throws Exception {
        //Lazy2_jaiSuo instance = Lazy2_jaiSuo.getInstance();
        Constructor<Lazy2_jaiSuo> declaredConstructor= Lazy2_jaiSuo.class.getDeclaredConstructor(null);//获取构造器 null为无参构造
        declaredConstructor.setAccessible(true); // 设置可以访问私有的构造器
        Lazy2_jaiSuo instance2 = declaredConstructor.newInstance();
        Lazy2_jaiSuo instance3 = declaredConstructor.newInstance();

        //System.out.println(instance);
        System.out.println(instance2);
        System.out.println(instance3);

    }

}
